package com.shenhaofeng.app.component.dialog.task;

import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentManager;

import com.shenhaofeng.app.log.AppLog;

import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;


/**
 * 包含异步任务的弹窗，在任务结束后弹窗将会消失。
 * 在以下的情况下，弹窗将会消失
 * <p>1.任务完成</p>
 * <p>2.任务执行过程中发生了异常</p>
 * <p>3.手动调用cancel,dismiss等方法</p>
 * Created by 沈豪烽 on 2016/9/2.
 */
public class AsyncTaskDialogFragment<R> extends DialogFragment implements DialogInterface.OnShowListener {

    private static final String TAG = "AsyncTaskDialogFragment";


    private Task<R> task;

    private Listener<R> listener;

    private Subscription taskSubscription;

    private boolean inTopView;

    private int dismissCount;


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //不完全销毁实例
        setRetainInstance(true);
    }


    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (getShowsDialog()) {
            //设置show的监听器
            getDialog().setOnShowListener(this);
        }
    }


    @Override
    public void onResume() {
        super.onResume();
        inTopView = true;
        if (dismissCount > 0) {
            dismissCount = 0;
            dismiss();
        }
    }


    @Override
    public void onPause() {
        super.onPause();
        inTopView = false;
    }


    @Override
    public void onShow(DialogInterface dialog) {
    }


    @Override
    public void onDismiss(DialogInterface dialog) {
        super.onDismiss(dialog);
        if (taskSubscription != null && !taskSubscription.isUnsubscribed()) {
            taskSubscription.unsubscribe();
            //如果任务为结束弹窗被销毁,立即通知取消任务
            onHandleCancel(listener);
        }
    }


    /**
     * 设置监听器
     *
     * @param listener
     */
    public void setListener(@NonNull Listener<R> listener) {
        this.listener = listener;
    }


    /**
     * 执行任务{@link Task}中请不要持有activity fragment等有生命周期的组件的实例,否则可能导致内存泄漏
     *
     * @param fragmentManager
     * @param tag
     * @param task
     */
    public void execute(FragmentManager fragmentManager, String tag, Task<R> task) {
        this.task = task;
        onExecuteShow(fragmentManager, tag);
    }


    protected void safeDismiss() {
        if (inTopView) {
            dismiss();
        } else {
            dismissCount++;
        }
    }


    /**
     * 调用方法启动异步任务
     */
    protected final void launchAsyncTask() {
        if (task == null || listener == null) {
            AppLog.e(TAG, "在启动AsyncTaskDialogFragment前必须调用setListener,并且task和listener都不能为null");
            safeDismiss();
        } else {
            taskSubscription = task.run()
                    .subscribeOn(Schedulers.newThread())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Action1<R>() {
                        @Override
                        public void call(R value) {
                            onHandleResult(listener, value);
                        }
                    }, new Action1<Throwable>() {
                        @Override
                        public void call(Throwable throwable) {
                            onHandleFailure(listener, throwable);
                        }
                    });

        }
    }


    /**
     * 在任务取消时将会被调用
     *
     * @param listener
     */
    protected void onHandleCancel(Listener<R> listener) {
        listener.onCancel();
    }


    /**
     * 该方法在结果被处理是将会被调用,如果需要自定义处理结果，请在该方法中处理
     *
     * @param listener
     * @param result
     */
    protected void onHandleResult(Listener<R> listener, R result) {
        listener.onResult(result);
        safeDismiss();
    }


    /**
     * 该方法在异常被处理是将会被调用,如果需要自定义处理结果，请在该方法中处理
     *
     * @param listener
     * @param throwable
     */
    protected void onHandleFailure(Listener<R> listener, Throwable throwable) {
        listener.onFailure(throwable);
        safeDismiss();
    }


    /**
     * 方法在接收到用户的{@link #execute(FragmentManager, String, Task)}调用后将被调用,覆写方法可以自行处理异步任务的调起时机
     *
     * @param fragmentManager
     * @param tag
     */
    protected void onExecuteShow(FragmentManager fragmentManager, String tag) {
        show(fragmentManager, tag);
        launchAsyncTask();
    }


    protected Listener<R> getListener() {
        return listener;
    }


}

